<template>
  <base-modal
    class="service-dialog-container"
    :title="$t('task.edit.chooseServiceItem')"
    :show.sync="visible"
    width="800px"
  >
    <div v-loading.lock="loading">
      <div class="search-panel">
        <el-input v-model="params.keyword" :placeholder="$t('task.tip.serviceTip1')" @keyup.enter.native="onSearch"></el-input>
        <el-button type="primary" @click="onSearch">{{$t('common.base.search')}}</el-button>
        <el-button @click="reset">{{$t('common.base.reset')}}</el-button>
      </div>

      <el-table
        ref="multipleTable"
        header-row-class-name="base-table-header-v3"
        row-class-name="base-table-row-v3"
        @select="handleSelection"
        @select-all="handleSelection"
        :data="data"
        border>
        <el-table-column
          type="selection"
          align="center"
          width="40"
        ></el-table-column>
        <el-table-column
          v-for="(column, index) in fields"
          :key="`${column.fieldName}_${index}`"
          :label="column.displayName"
          :prop="column.fieldName"
          show-overflow-tooltip>
          <template slot-scope="scope">
            <template v-if="column.fieldName === 'salePrice'">
              {{ scope.row | fmt_salePrice_currency }}
            </template>
            <template v-else>
              <span>{{ scope.row[column.fieldName] }}</span>
            </template>
          </template>
        </el-table-column>
      </el-table>

      <el-pagination
        class="comment-list-table-footer-pagination"
        @current-change="jump"
        @size-change="handleSizeChange"
        :page-sizes="defaultTableData.defaultPageSizes"
        :page-size="params.pageSize"
        :current-page="params.pageNum"
        :layout="defaultTableData.defaultLayout"
        :total="totalItems"
        background
      ></el-pagination>

      <div class="multiple-selection-panel">
        <el-tag
          v-for="tag in multipleSelection"
          :key="tag.id"
          type="info"
          @close="cancelSelect(tag)"
          closable>
          {{ tag.name }}
        </el-tag>
      </div>
    </div>

    <div slot="footer" class="dialog-footer">
      <el-button :disabled="pending" @click="visible = false">{{$t('common.base.cancel')}}</el-button>
      <el-button type="primary" :disabled="pending" @click="submit">{{$t('common.base.submit')}}</el-button>
    </div>
  </base-modal>
</template>

<script>
/* util */
import * as _ from 'lodash';
import { defaultTableData } from '@src/util/table'
/* model */
import { PART_SERVICE_LIST_MAX_LENGTH } from '@src/model/const/Number';

export default {
  name: 'choose-service-dialog',
  props: {
    colums: {
      type: Array,
      default: () => ([])
    }
  },
  data() {
    return {
      defaultTableData,
      loading: false,
      visible: false,
      pending: false,
      data: [],
      totalItems: 0,
      multipleSelection: [],
      params: this.buildParams() 
    }
  },
  computed: {
    fields() {
      let filterFields = ['preNum', 'total', 'action'];
      return this.colums.filter(item => filterFields.indexOf(item.fieldName) == -1);
    }
  },
  methods: {
    buildParams() {
      return {
        keyword: '',
        pageSize: 10,
        pageNum: 1
      }
    },
    /**
    * @description 打开添加服务项目弹窗
    */
    open() {
      this.data = [];
      this.totalItems = 0;

      this.params = this.buildParams();
      this.onSearch();

      this.multipleSelection = [];
      this.pending = false;
      this.visible = true;
    },
    /**
    * @description 关闭添加服务项目弹窗
    */
    close() {
      this.visible = false;
    },
    /**
    * @description 重置
    */
    reset() {
      this.params = this.buildParams();
      this.onSearch();
    },
    /**
    * @description 获取服务项目数据
    */
    onSearch() {
      this.loading = true;

      this.$http.post('/task/service/list', this.params)
        .then(res => {
          if (!res || !res.list) {
            this.data = [];
            this.totalItems = 0;
            this.params.pageNum = 1;
          } else {
            const { total, pageNum, list } = res;

            this.data = list.map(c => {
              c.preNum = 1;
              return c;
            })

            this.totalItems = total;
            this.params.pageNum = pageNum;

            this.matchSelected();
          }
        })
        .finally(() => {
          this.loading = false;
        })
        .catch(e => console.error(e));
    },
    /**
    * @description 勾选列表数据
    */
    handleSelection(selection) {
      let tv = this.selectionCompute(selection);
      
      // 当前页已选中数据
      let original = this.multipleSelection.filter(ms =>
        this.data.some(cs => cs.id === ms.id)
      );

      // 当前页未选中的数据
      let unSelected = this.data.filter(c =>
        original.every(oc => oc.id !== c.id)
      );

      // 超出可选限制时 不允许勾选
      if (tv.length > PART_SERVICE_LIST_MAX_LENGTH) {
        this.$nextTick(() => {
          original.length > 0
            ? unSelected.forEach(row => {
              this.$refs.multipleTable.toggleRowSelection(row, false);
            })
            : this.$refs.multipleTable.clearSelection();
        })

        return this.$platform.alert(this.$t('common.base.tip.selectAtMostTip', {max: PART_SERVICE_LIST_MAX_LENGTH}));
      }

      this.multipleSelection = tv;
    },
    /**
     * @description 计算已选择
     * @param {Array} selection 已选择列表
     * @return {Array} 计算过滤后的列表
    */
    selectionCompute(selection) {
      let tv = [];

      tv = this.multipleSelection.filter(ms =>
        this.data.every(c => c.id !== ms.id)
      )

      tv = _.uniqWith([...tv, ...selection], _.isEqual);
      return tv;
    },
    // 把选中的匹配出来
    matchSelected() {
      if (!this.multipleSelection.length) return;

      const selected = this.data.filter(c => {
        if (this.multipleSelection.some(sc => sc.id === c.id)) {
          this.multipleSelection = this.multipleSelection.filter(
            sc => sc.id !== c.id
          );
          this.multipleSelection.push(c);
          return c;
        }
      }) || [];

      this.$nextTick(() => {
        this.toggleSelection(selected);
      });
    },
    // 切换某行的选中状态
    toggleSelection(rows) {
      let isNotOnCurrentPage = false;
      let row = undefined;

      if (rows) {
        for (let i = 0; i < rows.length; i++) {
          row = rows[i];
          isNotOnCurrentPage = this.data.every(item => {
            return item.id !== row.id;
          });
          if (isNotOnCurrentPage) return;
        }
        rows.forEach(row => {
          this.$refs.multipleTable.toggleRowSelection(row);
        });
      } else {
        this.$refs.multipleTable.clearSelection();
        this.multipleSelection = [];
      }
    },
    /**
     * 取消选择的数据
    */
    cancelSelect (item) {
      this.multipleSelection = this.multipleSelection.filter(ms => ms.id !== item.id);
      this.toggleSelection([item]);
    },
    // 跳转至n页
    jump(pageNum) {
      this.params.pageNum = pageNum;
      this.onSearch();
    },
    // 切换一页n条
    handleSizeChange(pageSize) {
      this.params.pageNum = 1;
      this.params.pageSize = pageSize;
      this.onSearch();
    },
    /**
    * @description 提交
    */
    submit() {
      this.$emit('submit', this.multipleSelection);
    },
    togglePending(pending = false) {
      this.pending = pending;
    }
  }
}
</script>

<style lang="scss" scoped>
.service-dialog-container {
  ::v-deep .base-modal-body {
    padding: 16px 24px;
  }

  .search-panel {
    display: flex;
    
    .el-input {
      width: 300px;
      margin-right: 12px;
    }
  }

  .el-table {
    margin: 16px 0;

    input[type="number"] {
      width: 100%;
    }

    ::v-deep .el-checkbox {
      margin-bottom: 0;
    }

    ::v-deep .el-table-column--selection {
      .cell {
        padding-right: 10px !important;
      }
    }
  }

  .el-pagination {
    text-align: right;

    ::v-deep .el-pagination__jump {
      margin-left: 0;
    }
  }

  .multiple-selection-panel {
    padding-top: 12px;

    .el-tag {
      margin: 8px 8px 0 0;

      ::v-deep .el-icon-close {
        top: 1px;
      }
    }
  }
}
</style>